bitkeeper revision 1.42 (3e4e5147oIRUj1VB4sRCLLxTviTVaw)
authorkaf24@labyrinth.cl.cam.ac.uk <kaf24@labyrinth.cl.cam.ac.uk>
Sat, 15 Feb 2003 14:40:07 +0000 (14:40 +0000)
committerkaf24@labyrinth.cl.cam.ac.uk <kaf24@labyrinth.cl.cam.ac.uk>
Sat, 15 Feb 2003 14:40:07 +0000 (14:40 +0000)
network.c, dev.c, kernel.c:
  Fixed console export via UDP. Was rather broken. Still dropping external packets though :-(

xen-2.4.16/common/kernel.c
xen-2.4.16/common/network.c
xen-2.4.16/net/dev.c
xenolinux-2.4.16-sparse/arch/xeno/drivers/network/network.c

index 32e3dea59dac8dec81826fd20f7a50ee11764d4a..8a8c8ddd51eb0230720eb42294ec63c4308b789a 100644 (file)
@@ -398,39 +398,37 @@ typedef struct my_ethhdr {
     unsigned short  h_proto;        
 } my_ethhdr_t; 
 
-
+/*
+ * Function written by ek247. Exports console output from all domains upwards 
+ * to domain0, by stuffing it into a fake network packet.
+ */
 int console_export(char *str, int len)
 {
-    /* Function written by ek247
-     * Exports console output from all domains upwards
-     * to domain0, by stuffing it into a fake network
-     * packet
-     */
-    struct sk_buff *console_packet;
+    struct sk_buff *skb;
     struct my_iphdr *iph = NULL;  
     struct my_udphdr *udph = NULL; 
     struct my_ethhdr *ethh = NULL; 
     int hdr_size = sizeof(struct my_iphdr) + sizeof(struct my_udphdr); 
     u8 *skb_data;
 
-    // Prepare console packet - the grim + 20 in the alloc is for headroom.
-    console_packet = dev_alloc_skb(sizeof(struct my_ethhdr) + hdr_size + len + 20);
-    if (!console_packet) return 0;
-//console_packet->security = 9; // hack to trace these packets.
-    console_packet->dev = the_dev;
-    skb_data = map_domain_mem((unsigned long)console_packet->head);
-    skb_reserve(console_packet, 2); // ip header alignment.
-//printk("Eth is: %d\n", console_packet->data - console_packet->head);
-    ethh   = (struct my_ethhdr *) skb_data + (console_packet->data - console_packet->head);
-    skb_reserve(console_packet, sizeof(struct my_ethhdr)); 
-
-    skb_put(console_packet, hdr_size + len); 
-//printk("IP is: %d\n", console_packet->data - console_packet->head);
-    iph  = (struct my_iphdr *)skb_data + (console_packet->data - console_packet->head); 
+    skb = dev_alloc_skb(sizeof(struct my_ethhdr) + 
+                                   hdr_size + len + 20);
+    if ( skb == NULL ) return 0;
+
+    skb->dev = the_dev;
+    skb_data = (u8 *)map_domain_mem((skb->pf - frame_table) << PAGE_SHIFT);
+    skb_reserve(skb, 2);
+
+    /* Get a pointer to each header. */
+    ethh = (struct my_ethhdr *) 
+        (skb_data + (skb->data - skb->head));
+    iph  = (struct my_iphdr *)(ethh + 1);
     udph = (struct my_udphdr *)(iph + 1); 
-    memcpy((char *)(udph + 1), str, len); 
 
-    // Build IP header
+    skb_reserve(skb, sizeof(struct my_ethhdr)); 
+    skb_put(skb, hdr_size + len); 
+
+    /* Build IP header. */
     iph->version = 4;
     iph->ihl     = 5;
     iph->frag_off= 0;
@@ -440,33 +438,31 @@ int console_export(char *str, int len)
     iph->daddr   = htonl(opt_ipbase);
     iph->saddr   = htonl(0xa9fe0001); 
     iph->tot_len = htons(hdr_size + len); 
-
-    // Calculating IP checksum
     iph->check  = 0;
     iph->check   = compute_cksum((__u16 *)iph, sizeof(struct my_iphdr)/2); 
 
+    /* Build UDP header. */
+    udph->source = htons(current->domain);
+    udph->dest   = htons(666);
+    udph->len    = htons(sizeof(struct my_udphdr) + len);
+    udph->check  = 0;
+
+    /* Build the UDP payload. */
+    memcpy((char *)(udph + 1), str, len); 
 
-    // Build UDP header
-    udph->source    = htons(current->domain);
-    udph->dest      = htons(666);
-    udph->len       = htons(sizeof(struct my_udphdr) + len);
-    udph->check     = 0;
-               
-    // Fix Ethernet header
-    memcpy(ethh->h_source, "000000", 6);
-    memcpy(ethh->h_dest, "000000", 6);
+    /* Fix Ethernet header. */
+    memset(ethh->h_source, 0, ETH_ALEN);
+    memset(ethh->h_dest,   0, ETH_ALEN);
     ethh->h_proto = htons(ETH_P_IP);
-    console_packet->mac.ethernet= (struct ethhdr *)ethh;
+    skb->mac.ethernet= (struct ethhdr *)ethh;
 
-    // Make the packet appear to come off the external NIC so that the 
-    // tables code doesn't get too confused.
-    console_packet->src_vif = VIF_PHYSICAL_INTERFACE;
-    console_packet->dst_vif = 0;
+    /* Keep the net rule tables happy. */
+    skb->src_vif = VIF_PHYSICAL_INTERFACE;
+    skb->dst_vif = 0;
     
     unmap_domain_mem(skb_data);
     
-    // Pass the packet to netif_rx
-    (void)netif_rx(console_packet);
+    (void)netif_rx(skb);
 
     return 1;
 }
index 3afc59b54f3e3c734e799b4b8eae7dce581470d5..80fad27cc7e9d31775ec0bab86049bda47b65e44 100644 (file)
@@ -356,20 +356,18 @@ int __net_get_target_vif(u8 *data, unsigned int len, int src_vif)
     switch ( ntohs(*(unsigned short *)(data + 12)) )
     {
     case ETH_P_ARP:
-//printk("ARP!\n");
         if ( len < 28 ) goto drop;
         target = net_find_rule((u8)ETH_P_ARP, 0, ntohl(*(u32 *)(nh_raw + 14)),
                         ntohl(*(u32 *)(nh_raw + 24)), 0, 0, 
                         src_vif);
         break;
+
     case ETH_P_IP:
-//printk("IP\n");
         if ( len < 20 ) goto drop;
         h_raw =  data + ((*(unsigned char *)(nh_raw)) & 0x0f) * 4;
         switch ( *(unsigned char *)(nh_raw + 9) )
         {
         case IPPROTO_UDP:
-//printk("UDP!\n");
         case IPPROTO_TCP:
             target = net_find_rule((u8)ETH_P_IP,  *(u8 *)(nh_raw + 9),
                     ntohl(*(u32 *)(nh_raw + 12)),
@@ -378,8 +376,8 @@ int __net_get_target_vif(u8 *data, unsigned int len, int src_vif)
                     ntohs(*(u16 *)(h_raw + 2)), 
                     src_vif);
             break;
+
         default: // ip-based protocol where we don't have ports.
-//printk("Other IP!\n");
             target = net_find_rule((u8)ETH_P_IP,  *(u8 *)(data + 9),
                     ntohl(*(u32 *)(nh_raw + 12)),
                     ntohl(*(u32 *)(nh_raw + 16)),
@@ -388,6 +386,7 @@ int __net_get_target_vif(u8 *data, unsigned int len, int src_vif)
                     src_vif);
         }
         break;
+
     }
     return target;
     
index f5d85547a510ddd4194f78d1ece6e544d8e2447d..4e36aa0d608d8ca28d97bd84fa5522094a620805 100644 (file)
@@ -46,7 +46,6 @@
 #define DPRINTK(_f, _a...) ((void)0)
 #endif
 
-// Ring defines:
 #define TX_RING_INC(_i)    (((_i)+1) & (TX_RING_SIZE-1))
 #define RX_RING_INC(_i)    (((_i)+1) & (RX_RING_SIZE-1))
 #define TX_RING_ADD(_i,_j) (((_i)+(_j)) & (TX_RING_SIZE-1))
@@ -689,8 +688,6 @@ void deliver_packet(struct sk_buff *skb, net_vif_t *vif)
         struct pfn_info *g_pfn, *h_pfn;
         unsigned int i; 
 
-        
-        
         memset(skb->mac.ethernet->h_dest, 0, ETH_ALEN);
         if ( ntohs(skb->mac.ethernet->h_proto) == ETH_P_ARP )
         {
@@ -698,44 +695,47 @@ void deliver_packet(struct sk_buff *skb, net_vif_t *vif)
         }
         shadow_ring = vif->shadow_ring;
 
-        //Advance to next good buffer.
-        for (i = shadow_ring->rx_cons; 
-             (i != shadow_ring->rx_prod) 
-             && ( shadow_ring->rx_ring[i].status != RING_STATUS_OK );
-             i = RX_RING_INC(i));
-            
-        if (( i != shadow_ring->rx_prod ) &&
-            ( shadow_ring->rx_ring[i].status == RING_STATUS_OK ))
+        if ( (i = shadow_ring->rx_cons) == shadow_ring->rx_prod )
         {
-            rx = shadow_ring->rx_ring+i;
-            if ( (skb->len + ETH_HLEN) < rx->size )
-                rx->size = skb->len + ETH_HLEN;
-            
-            g_pte = map_domain_mem(rx->addr);
-
-            g_pfn =  frame_table + (*g_pte >> PAGE_SHIFT);
-            h_pfn = skb->pf;
+            return;
+        }
 
-            h_pfn->tot_count = h_pfn->type_count = 1;
-            g_pfn->tot_count = g_pfn->type_count = 0;
-            h_pfn->flags = g_pfn->flags & (~PG_type_mask);
+        if ( shadow_ring->rx_ring[i].status != RING_STATUS_OK )
+        {
+            DPRINTK("Bad buffer in deliver_packet()\n");
+            shadow_ring->rx_cons = RX_RING_INC(i);
+            return;
+        }
 
-            if (*g_pte & _PAGE_RW) h_pfn->flags |= PGT_writeable_page;
-            g_pfn->flags = 0;
+        rx = shadow_ring->rx_ring + i;
+        if ( (skb->len + ETH_HLEN) < rx->size )
+            rx->size = skb->len + ETH_HLEN;
             
-            //point guest pte at the new page:
-            machine_to_phys_mapping[h_pfn - frame_table] 
-                    = machine_to_phys_mapping[g_pfn - frame_table];
+        g_pte = map_domain_mem(rx->addr);
 
-            *g_pte = (*g_pte & ~PAGE_MASK) 
-                | (((h_pfn - frame_table) << PAGE_SHIFT) & PAGE_MASK);
-            *g_pte |= _PAGE_PRESENT;
-                
-            unmap_domain_mem(g_pte);
-            skb->pf = g_pfn; // return the guest pfn to be put on the free list
-                
-            shadow_ring->rx_cons = RX_RING_INC(i);
-        }
+        g_pfn = frame_table + (*g_pte >> PAGE_SHIFT);
+        h_pfn = skb->pf;
+        
+        h_pfn->tot_count = h_pfn->type_count = 1;
+        g_pfn->tot_count = g_pfn->type_count = 0;
+        h_pfn->flags = g_pfn->flags & (~PG_type_mask);
+        
+        if (*g_pte & _PAGE_RW) h_pfn->flags |= PGT_writeable_page;
+        g_pfn->flags = 0;
+        
+        /* Point the guest at the new machine frame. */
+        machine_to_phys_mapping[h_pfn - frame_table] 
+            = machine_to_phys_mapping[g_pfn - frame_table];        
+        *g_pte = (*g_pte & ~PAGE_MASK) 
+            | (((h_pfn - frame_table) << PAGE_SHIFT) & PAGE_MASK);
+        *g_pte |= _PAGE_PRESENT;
+        
+        unmap_domain_mem(g_pte);
+
+        /* Our skbuff now points at the guest's old frame. */
+        skb->pf = g_pfn;
+        
+        shadow_ring->rx_cons = RX_RING_INC(i);
 }
 
 /* Deliver skb to an old protocol, which is not threaded well
@@ -785,17 +785,17 @@ int netif_rx(struct sk_buff *skb)
         
         skb->head = (u8 *)map_domain_mem(((skb->pf - frame_table) << PAGE_SHIFT));
 
-        /* remapping this address really screws up all the skb pointers.  We need 
-         * to map them all here sufficiently to get the packet demultiplexed.
-         *
-         * this remapping happens more than once in the code and is grim.  It will
-         * be fixed in a later update -- drivers should be able to align the packet
-         * arbitrarily.
+        /*
+         * remapping this address really screws up all the skb pointers.  We
+         * need to map them all here sufficiently to get the packet
+         * demultiplexed. this remapping happens more than once in the code and
+         * is grim.  It will be fixed in a later update -- drivers should be
+         * able to align the packet arbitrarily.
          */
                 
         skb->data = skb->head;
-        skb_reserve(skb,18); // 18 is the 16 from dev_alloc_skb plus 2 for #
-                             // IP header alignment. 
+        skb_reserve(skb,18); /* 18 is the 16 from dev_alloc_skb plus 2 for
+                                IP header alignment. */
         skb->mac.raw = skb->data;
         skb->data += ETH_HLEN;
         skb->nh.raw = skb->data;
@@ -813,14 +813,14 @@ int netif_rx(struct sk_buff *skb)
         if ( (vif = sys_vif_list[skb->dst_vif]) == NULL )
             goto drop;
 
-        /* This lock-and-walk of the task list isn't really necessary, and is an
-         * artifact of the old code.  The vif contains a pointer to the skb list 
-         * we are going to queue the packet in, so the lock and the inner loop
-         * could be removed.
-         *
-         * The argument against this is a possible race in which a domain is killed
-         * as packets are being delivered to it.  This would result in the dest vif
-         * vanishing before we can deliver to it.
+        /*
+         * This lock-and-walk of the task list isn't really necessary, and is
+         * an artifact of the old code.  The vif contains a pointer to the skb
+         * list we are going to queue the packet in, so the lock and the inner
+         * loop could be removed. The argument against this is a possible race
+         * in which a domain is killed as packets are being delivered to it.
+         * This would result in the dest vif vanishing before we can deliver to
+         * it.
          */
         
         if ( skb->dst_vif >= VIF_PHYSICAL_INTERFACE )
@@ -974,11 +974,11 @@ static inline void handle_diverter(struct sk_buff *skb)
 
 /*
  * update_shared_ring(void)
- *
- * This replaces flush_rx_queue as the guest event handler to move packets queued in
- * the guest ring up to the guest.  Really, the packet is already there, it was page
- * flipped in deliver_packet, but this moves the ring descriptor across from the 
- * shadow ring and increments the pointers.
+ * 
+ * This replaces flush_rx_queue as the guest event handler to move packets
+ * queued in the guest ring up to the guest.  Really, the packet is already
+ * there, it was page flipped in deliver_packet, but this moves the ring
+ * descriptor across from the shadow ring and increments the pointers.
  */
 
 void update_shared_ring(void)
@@ -990,32 +990,37 @@ void update_shared_ring(void)
     unsigned int nvif;
     
     clear_bit(_HYP_EVENT_NET_RX, &current->hyp_events);
-    for (nvif = 0; nvif < current->num_net_vifs; nvif++)
+
+    for ( nvif = 0; nvif < current->num_net_vifs; nvif++ )
     {
         net_ring = current->net_vif_list[nvif]->net_ring;
         shadow_ring = current->net_vif_list[nvif]->shadow_ring;
-        while ((shadow_ring->rx_idx != shadow_ring->rx_cons) 
-                && (net_ring->rx_cons != net_ring->rx_prod))
+        
+        if ( shadow_ring->rx_idx != net_ring->rx_cons )
         {
-            rx = shadow_ring->rx_ring+shadow_ring->rx_idx;
-            copy_to_user(net_ring->rx_ring + net_ring->rx_cons, rx, sizeof(rx_entry_t));
+            DPRINTK("Shadow and shared rings out of sync (%d/%d)\n",
+                    shadow_ring->rx_idx, net_ring->rx_cons);
+        }
+
+        while ( (shadow_ring->rx_idx != shadow_ring->rx_cons) &&
+                (net_ring->rx_cons != net_ring->rx_prod) )
+        {
+            rx = shadow_ring->rx_ring + shadow_ring->rx_idx;
+            copy_to_user(net_ring->rx_ring + net_ring->rx_cons, rx, 
+                         sizeof(rx_entry_t));
 
             shadow_ring->rx_idx = RX_RING_INC(shadow_ring->rx_idx);
             net_ring->rx_cons   = RX_RING_INC(net_ring->rx_cons);
             
-            if (rx->flush_count == tlb_flush_count[smp_processor_id()])
+            if ( rx->flush_count == tlb_flush_count[smp_processor_id()] )
                 __flush_tlb();
 
             if ( net_ring->rx_cons == net_ring->rx_event )
                 set_bit(_EVENT_NET_RX, &s->events);
-            
         }
     }
 }
-            
-/*
- *     Map an interface index to its name (SIOCGIFNAME)
- */
+
 
 /*
  *     We need this ioctl for efficient implementation of the
@@ -2024,7 +2029,9 @@ void tx_skb_release(struct sk_buff *skb)
  * Called from guest OS to notify updates to its transmit and/or receive
  * descriptor rings.
  */
-#define PKT_PROT_LEN (ETH_HLEN + 8)
+
+/* Ethernet + IP headers */
+#define PKT_PROT_LEN (ETH_HLEN + 20)
 
 long do_net_update(void)
 {
@@ -2049,35 +2056,49 @@ long do_net_update(void)
 
         current_vif = current->net_vif_list[j];
         net_ring = current_vif->net_ring;
-
-        /* First, we send out pending TX descriptors if they exist on this ring.
-         */
         
-        for ( i = net_ring->tx_cons; i != net_ring->tx_prod; i = TX_RING_INC(i) )
+        /*
+         * PHASE 1 -- TRANSMIT RING
+         */
+
+        for ( i = net_ring->tx_cons; 
+              i != net_ring->tx_prod; 
+              i = TX_RING_INC(i) )
         {
             if ( copy_from_user(&tx, net_ring->tx_ring+i, sizeof(tx)) )
+            {
+                DPRINTK("Bad copy_from_user for tx net descriptor\n");
                 continue;
+            }
+
+            if ( tx.size < PKT_PROT_LEN )
+            {
+                DPRINTK("Runt packet %ld\n", tx.size);
+                continue; 
+            }
 
-            if ( tx.size < PKT_PROT_LEN ) continue; 
-            
             if ( ((tx.addr & ~PAGE_MASK) + tx.size) >= PAGE_SIZE ) 
             {
-                DPRINTK("tx.addr: %lx, size: %lu, end: %lu\n", tx.addr, tx.size,
-                    (tx.addr &~PAGE_MASK) + tx.size);
+                DPRINTK("tx.addr: %lx, size: %lu, end: %lu\n", 
+                        tx.addr, tx.size, (tx.addr &~PAGE_MASK) + tx.size);
                 continue;
             }
             
             if ( TX_RING_INC(i) == net_ring->tx_event )
+            {
                 set_bit(_EVENT_NET_TX, &shared->events);
+            }
 
-            /* Map the skb in from the guest, and get it's delivery target.
+            /* 
+             * Map the skb in from the guest, and get it's delivery target.
              * We need this to know whether the packet is to be sent locally
              * or remotely.
              */
             
             g_data = map_domain_mem(tx.addr);
 
-            protocol = __constant_htons(init_tx_header(g_data, tx.size, the_dev));
+            protocol = __constant_htons(
+                init_tx_header(g_data, tx.size, the_dev));
             if ( protocol == 0 )
             {
                 unmap_domain_mem(g_data);
@@ -2088,9 +2109,7 @@ long do_net_update(void)
 
             if (target > VIF_PHYSICAL_INTERFACE )
             {
-                // Local delivery: Allocate an skb off the domain free list
-                // fil it, and pass it to netif_rx as if it came off the NIC.
-
+                /* Local delivery */
                 skb = dev_alloc_skb(tx.size);
 
                 if (skb == NULL) 
@@ -2103,26 +2122,25 @@ long do_net_update(void)
                 skb->dst_vif = target;
                 skb->protocol = protocol;
                 
-                skb->head = (u8 *)map_domain_mem(((skb->pf - frame_table) << PAGE_SHIFT));
+                skb->head = (u8 *)map_domain_mem(
+                    ((skb->pf - frame_table) << PAGE_SHIFT));
                 skb->data = skb->head + 16;
                 skb_reserve(skb,2);
                 memcpy(skb->data, g_data, tx.size);
                 skb->len = tx.size;
                 unmap_domain_mem(skb->head);
-                skb->data += ETH_HLEN; // so the assertion in netif_RX doesn't freak out.
-                
+                skb->data += ETH_HLEN;
                 (void)netif_rx(skb);
-
                 unmap_domain_mem(g_data);
             }
             else if ( target == VIF_PHYSICAL_INTERFACE )
             {
-                // External delivery: Allocate a small skb to hold protected header info
-                // and copy the eth header and IP address fields into that.
-                // Set a frag link to the remaining data, and we will scatter-gather
-                // in the device driver to send the two bits later.
-                
-                skb = alloc_skb(PKT_PROT_LEN, GFP_KERNEL); // Eth header + two IP addrs.
+                /*
+                 * External delivery: create a fragmented SKB, consisting of a
+                 * small copied section for the header, then a reference to the
+                 * in-place payload.
+                 */                
+                skb = alloc_skb(PKT_PROT_LEN, GFP_KERNEL);
                 if (skb == NULL) 
                     continue;
             
@@ -2136,15 +2154,13 @@ long do_net_update(void)
                 skb->protocol = protocol; 
                 skb->mac.raw=skb->data; 
 
-                // set tot_count++ in the guest data pfn.
+                /* One more reference to guest page for duration of transfer */
                 page = (tx.addr >> PAGE_SHIFT) + frame_table;
                 page->tot_count++;
                 
-                // assign a destructor to the skb that will unlink and dec the tot_count
+                /* We have special destructor to deal with guest frag. */
                 skb->destructor = &tx_skb_release;
 
-                // place the remainder of the packet (which is in guest memory) into an
-                // skb frag.
                 skb_shinfo(skb)->frags[0].page = page;
                 skb_shinfo(skb)->frags[0].size = tx.size - PKT_PROT_LEN;
                 skb_shinfo(skb)->frags[0].page_offset 
@@ -2162,60 +2178,67 @@ long do_net_update(void)
         }
         net_ring->tx_cons = i;
 
-        /* Next, pull any new RX descriptors across to the shadow ring.
+        /*
+         * PHASE 2 -- RECEIVE RING
          */
-    
+
         shadow_ring = current_vif->shadow_ring;
 
-        for (i = shadow_ring->rx_prod; i != net_ring->rx_prod; i = RX_RING_INC(i))
+        for ( i = shadow_ring->rx_prod; 
+              i != net_ring->rx_prod; 
+              i = RX_RING_INC(i) )
         {
-            /* This copy assumes that rx_shadow_entry_t is an extension of 
+            /* 
+             * This copy assumes that rx_shadow_entry_t is an extension of 
              * rx_net_entry_t extra fields must be tacked on to the end.
              */
             if ( copy_from_user( shadow_ring->rx_ring+i, net_ring->rx_ring+i, 
                                  sizeof (rx_entry_t) ) )
             {
+                DPRINTK("Bad copy_from_user for rx ring\n");
                 shadow_ring->rx_ring[i].status = RING_STATUS_ERR_CFU;
                 continue;
-            } else {
-                    
-                rx = shadow_ring->rx_ring + i;
-                pfn = rx->addr >> PAGE_SHIFT;
-                page = frame_table + pfn;
-                
-                shadow_ring->rx_ring[i].status = RING_STATUS_BAD_PAGE;
-
-                if  ( page->flags != (PGT_l1_page_table | current->domain) ) 
-                {
-                       continue;
-                }
-
-
-                g_pte = map_domain_mem(rx->addr);
-
-                if (!(*g_pte & _PAGE_PRESENT))
-                {
-                        unmap_domain_mem(g_pte);
-                        continue;
-                }
-                
-                page = (*g_pte >> PAGE_SHIFT) + frame_table;
-                
-                if (page->tot_count != 1) 
-                {
-                        unmap_domain_mem(g_pte);
-                        continue;
-                }
-                
-                // The pte they passed was good, so we take it away from them.
-                shadow_ring->rx_ring[i].status = RING_STATUS_OK;
-                *g_pte &= ~_PAGE_PRESENT;
-                page->flags = (page->flags & ~PG_type_mask) | PGT_net_rx_buf;
-                rx->flush_count = tlb_flush_count[smp_processor_id()];
+            } 
 
+            rx = shadow_ring->rx_ring + i;
+            pfn = rx->addr >> PAGE_SHIFT;
+            page = frame_table + pfn;
+            
+            shadow_ring->rx_ring[i].status = RING_STATUS_BAD_PAGE;
+            
+            if  ( page->flags != (PGT_l1_page_table | current->domain) ) 
+            {
+                DPRINTK("Bad page flags\n");
+                continue;
+            }
+            
+            g_pte = map_domain_mem(rx->addr);
+            
+            if (!(*g_pte & _PAGE_PRESENT))
+            {
+                DPRINTK("Inavlid PTE passed down (not present)\n");
                 unmap_domain_mem(g_pte);
+                continue;
             }
+            
+            page = (*g_pte >> PAGE_SHIFT) + frame_table;
+            
+            if (page->tot_count != 1) 
+            {
+                DPRINTK("An rx page must be mapped exactly once\n");
+                unmap_domain_mem(g_pte);
+                continue;
+            }
+            
+            /* The pte they passed was good, so take it away from them. */
+            shadow_ring->rx_ring[i].status = RING_STATUS_OK;
+            *g_pte &= ~_PAGE_PRESENT;
+            page->flags = (page->flags & ~PG_type_mask) | PGT_net_rx_buf;
+            rx->flush_count = tlb_flush_count[smp_processor_id()];
+            
+            unmap_domain_mem(g_pte);
         }
+        smp_wmb(); /* Let other CPUs see new descriptors first. */
         shadow_ring->rx_prod = net_ring->rx_prod;
     }
     return 0;
index 0eb8003512286518f61b36a9f9d2a6f2ea084e69..b87ef4a09014e25ab6f48926e6e016f3a90a8ab3 100644 (file)
@@ -46,8 +46,6 @@ static void cleanup_module(void);
 
 static struct list_head dev_list;
 
-static unsigned int net_countx;
-
 /*
  * RX RING:   RX_IDX <= rx_cons <= rx_prod
  * TX RING:   TX_IDX <= tx_cons <= tx_prod
@@ -171,15 +169,14 @@ static void network_tx_buf_gc(struct net_device *dev)
 
 inline unsigned long get_ppte(unsigned long addr)
 {
-    unsigned long ppte = 0xdeadbeef;
+    unsigned long ppte;
     pgd_t *pgd; pmd_t *pmd; pte_t *ptep;
     pgd = pgd_offset_k(addr);
 
-    if (pgd_none(*pgd) || pgd_bad(*pgd)) BUG();
+    if ( pgd_none(*pgd) || pgd_bad(*pgd) ) BUG();
         
     pmd = pmd_offset(pgd, addr);
-    if (pmd_none(*pmd)) BUG(); 
-    if (pmd_bad(*pmd)) BUG();
+    if ( pmd_none(*pmd) || pmd_bad(*pmd) ) BUG(); 
         
     ptep = pte_offset(pmd, addr);
     ppte = (unsigned long)phys_to_machine(virt_to_phys(ptep));
@@ -202,7 +199,7 @@ static void network_alloc_rx_buffers(struct net_device *dev)
         skb->dev = dev;
         skb_reserve(skb, 2); /* word align the IP header */
         np->rx_skb_ring[i] = skb;
-        np->net_ring->rx_ring[i].addr = get_ppte(skb->head); 
+        np->net_ring->rx_ring[i].addr = get_ppte((unsigned long)skb->head); 
         np->net_ring->rx_ring[i].size = RX_BUF_SIZE - 16; /* arbitrary */
     }
 
@@ -310,11 +307,10 @@ static void network_rx_int(int irq, void *dev_id, struct pt_regs *ptregs)
         skb->protocol = eth_type_trans(skb, dev);
 
         /*
-         * Set up shinfo -- from alloc_skb This was particularily nasty:  the 
-         * shared info is hidden at the back of the data area (presumably so 
-         * it can be shared), but on page flip it gets very spunked.
+         * Set up shinfo -- from alloc_skb This was particularily nasty:  the
+         * shared info is hidden at the back of the data area (presumably so it
+         * can be shared), but on page flip it gets very spunked.
          */
-
         atomic_set(&(skb_shinfo(skb)->dataref), 1);
         skb_shinfo(skb)->nr_frags = 0;
         skb_shinfo(skb)->frag_list = NULL;